iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Modern Web

一些讓你看來很強的 ORM - prisma系列 第 17

Day17. 一些讓你看來很強的 ORM - prisma (Validator)下

  • 分享至 

  • xImage
  •  

看完昨天的 prisma validator 的功能後,大家對 type safe 是不是又更了解了呢?今天補充一些情境讓你不得不用 prisma validator

介紹

以下是今天的 demo 會用到的 model,簡單加上一個 Usermodel 然後用一對多的關聯式去 relation Post

model User {
  id    Int     @id
  email String  @unique
  name  String?
  posts Post[]
}

model Post {
  id        Int     @id
  author    User    @relation(fields: [userId], references: [id])
  title     String
  published Boolean @default(false)
  userId    Int
}

每當我們 migrate DBprisma client 會自動產生以下的 type 這邊來說就是 User

export declare type User = {
  id: string
  email: string
  name: string | null
}

但這時我們可能會遇到一個情境會是,假設你有一個 function 然後需要定義 User returntype,但仔細看一下 User type 他並沒有任何關於 post 的內容 ,原因就是 prisma 預設不會 return relationdata ,同時也不會產生關於 post 的型別,所以這時候我們只能自己 customize 我們要的 User type 同時包含 post 的內容

所以你會去定義如以下的 UserWithPosts 以及 UserPersonalData 來區別 returndata 是否有 post

// 1: Define a type that includes the relation to `Post`
type UserWithPosts = {
  id: string
  email: string
  name: string | null
  posts: Post[]
}

// 2: Define a type that only contains a subset of the scalar fields
type UserPersonalData = {
  email: string
  name: string | null
}

以上的寫法雖然很有彈性,但其實對於日後維護會添加很多成本,原因是每當你重新 generate prisma client 都需要手動去 update UserWithPostsUserPersonalData 的型別,但其實你不用這麼麻煩,prisma 有提供 utils function 自動給你你要的 type

import { Prisma } from '@prisma/client'

// 1: Define a type that includes the relation to `Post`
const userWithPosts = Prisma.validator<Prisma.UserDefaultArgs>()({
  include: { posts: true },
})

// 2: Define a type that only contains a subset of the scalar fields
const userPersonalData = Prisma.validator<Prisma.UserDefaultArgs>()({
  select: { email: true, name: true },
})

// 3: This type will include a user and all their posts
type UserWithPosts = Prisma.UserGetPayload<typeof userWithPosts>

以上的寫法可以讓整體的 code 更乾淨,同時對於日後維護也更方便

Return Type

另外一個情境會是當我們使用 include 或是 select 的時候我們很難拿到 getUsersWithPostsreturn type

async function getUsersWithPosts() {
  const users = await prisma.user.findMany({ include: { posts: true } })
  return users
}

所以常見的情況會是,我們要訂很多的 type 去拿到 getUsersWithPosts return 的型別

// Function definition that returns a partial structure
async function getUsersWithPosts() {
  const users = await prisma.user.findMany({ include: { posts: true } })
  return users
}

// Extract `UsersWithPosts` type with
type ThenArg<T> = T extends PromiseLike<infer U> ? U : T
type UsersWithPosts = ThenArg<ReturnType<typeof getUsersWithPosts>>

// run inside `async` function
const usersWithPosts: UsersWithPosts = await getUsersWithPosts()

但其實我們可以直接用 Prisma.PromiseReturnType 就可以簡單拿到我們要的 type

import { Prisma } from '@prisma/client'

type UsersWithPosts = Prisma.PromiseReturnType<typeof getUsersWithPosts>

大家如果有問題可以來小弟的群組討論~

✅ 前端社群 :
https://lihi3.cc/kBe0Y


上一篇
Day16. 一些讓你看來很強的 ORM - prisma (Validator)上
下一篇
Day18. 一些讓你看來很強的 ORM - prisma (zod validate)
系列文
一些讓你看來很強的 ORM - prisma30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言